// ----------------------------------------
// Filename: Scheduler.h
// Description: The header file for the Scheduler
// Author: Jon Maloney
// Date: 9-May-2012
//

#ifndef _SCHEDULER_H
#define _SCHEDULER_H

//************************************************************
//                    Include .h files
//************************************************************
#include "Ready_Queue.h"
#include "Linked_List.h"
#include "thread.h"
#include "microRTOS.h"

//************************************************************
//                    Include external references
//************************************************************
extern void vContextSwitch( void );

//************************************************************
//                    Define Statements
//************************************************************

//Calls the assembly instructions that perform
//	a context switch
#define ContextSwitch()				asm volatile (  "CALL _vContextSwitch	\n	"	\
													"NOP						");

//Restore context used for starting the scheduler
#define RESTORE_CONTEXT()																						\
		asm volatile(	"MOV	_currentRunningTask, W0		\n"	/* Restore the stack pointer for the task. */				\
						"MOV	[W0], W15					\n"																\
						"POP	W0							\n"	/* Restore the critical nesting counter for the task. */	\
						"MOV	W0, _uxCriticalNesting		\n"																\
						"POP	PSVPAG						\n"																\
						"POP	CORCON						\n"																\
						"POP	TBLPAG						\n"																\
						"POP	RCOUNT						\n"	/* Restore the registers from the stack. */					\
						"POP	W14							\n"																\
						"POP.D	W12							\n"																\
						"POP.D	W10							\n"																\
						"POP.D	W8							\n"																\
						"POP.D	W6							\n"																\
						"POP.D	W4							\n"																\
						"POP.D	W2							\n"																\
						"POP.D	W0							\n"																\
						"POP	SR						  	  " );

//************************************************************
//                    Struct, Union, enum Statements
//************************************************************

typedef enum 
{
	eRateMonotonic, 
	eEarliestDeadlineFirst
} eSchedulingAlgorithm;

#define SCEDULING_ALGORITHM eRateMonotonic

//************************************************************
//                    Global variables and constants
//************************************************************

//************************************************************
//                    Prototype Global Functions
//************************************************************

// ----------------------------------------
// Scheduler_GetTickCount
// 
// Returns the current system tick Count
//
// Input:
//	none
// Output:
//  The current tick value
// Conditions:
// 	none
UINT16 Scheduler_GetTickCount();

// ----------------------------------------
// Scheduler_DeleteTask
// 
// Deletes a task from the system
//
// Input:
//	none
// Output:
//  The current tick value
// Conditions:
// 	none
void Scheduler_DeleteTask(linkedList_Handle taskList);

// ----------------------------------------
// Scheduler_FindPriorityTaskItem
// 
// Finds the highest priority thead in the queue. 
// Input:
//  taskList: A pointer to the list of tasks from which
//				the highest priority task will be found
// Output:
//   A handle to the list item that contains the highest priority task found in the list.
// Conditions:
// 	none
linkedList_Handle Scheduler_FindPriorityTaskItem(linkedList_Handle taskList);

// ----------------------------------------
// Scheduler_FindPriorityTask
// 
// Finds the highest priority thead in the queue. 
// Input:
//  taskList: A pointer to the list of tasks from which
//				the highest priority task will be found
// Output:
//   A handle to the TCB of the highest priority task found in the list.
// Conditions:
// 	none
TCB * Scheduler_FindPriorityTask( T_READY_QUEUE * rQueue );

// ----------------------------------------
// Scheduler_MoveTaskToReadyQueue
// 
// Moves a task from the list it is contained in to the ready Queue
// Input:
//  taskList: A pointer to the list item of tasks from which
//				which contains the task to be moved.
// Output:
//   none
// Conditions:
// 	none
void Scheduler_MoveTaskToReadyQueue(linkedList_Handle nextPriorityTask);

// ----------------------------------------
// Scheduler_DemoteTask
// 
// To be used in conjunciton with TemporarilyPromoteThread
//	this funciton will restore the task back to its original priority
//	
// Input:
//  taskList: A pointer to the list node where the task is located.
// Output:
//   none
// Conditions:
// 	The task must be on the ready queue before this function is called.
//	This is different from ready queue move because ready queue move 
//	protects the ready queue by preventing tasks not on the ready queue
//	from being removed. This fucntion has no such protection.
void Scheduler_DemoteTask(linkedList_Handle taskToAddNode);

// ----------------------------------------
// Scheduler_AddTaskNodeToReadyQueue
// 
// Adds a task to the ready Queue
// Input:
//  taskList: A pointer to the list node of tasks from which
//				which contains the task to be moved.
// Output:
//   none
// Conditions:
// 	none
BOOL Scheduler_AddTaskNodeToReadyQueue(linkedList_Handle taskToAddNode);


// ----------------------------------------
// Scheduler_AddTaskToReadyQueue
// 
// Adds a task to the ready Queue
// Input:
//  taskList: A pointer to the task to be added
//				to the ready queue
// Output:
//   A handle to the task node used by the scheduler 
//		to track the task.
// Conditions:
// 	none
linkedList_Handle Scheduler_AddTaskToReadyQueue(TCB * task);

// ----------------------------------------
// Scheduler_Delay
// 
//  Loads the currently running task into the waiting queue
//	for the delayTime.
//
// Input:
// 	delayTime: 	The time in ticks that the current task is to be
//				delayed for.
// Output:
//   none
// Conditions:
// 	none
void Scheduler_Delay(kernelTickType delayTime);

// ----------------------------------------
// Scheduler_PreEmptiveContextSwitch
// 
//  If there is a higher priority task in the 
//	waiting queue a context switch will be performed.
//	
//	When performing a context switch the the currently running
//	task is placed on the ready queue and the next highest priority
//	task is switched in.
//
//	If there is a task on the ready queue of equal priority to the task
//	running a context switch will be performed.
//
// Input:
// 	none
// Output:
//   none
// Conditions:
// 	none
void Scheduler_PreEmptiveContextSwitch( void );

// ----------------------------------------
// Scheduler_PreEmptiveContextSwitch
// 
//  If the currently running task is in the running state
//	a pre-emptive context switch will be performed. See
//	(Scheduler_PreEmptiveContextSwitch)
//
//	If the currently running task is no longer running
//	the next highest priority task will be switched in.
//
// Input:
// 	none
// Output:
//   none
// Conditions:
// 	none
void Scheduler_TaskYeild( void );

// ----------------------------------------
// scheduler_SwitchInNextPriorityTask
// 
//  This function is only to be used by the contextSwitch function.
//	
//	The function gets the next highest priority task from the ready queue
//	and makes this task the currently running task.
//
// Input:
// 	none
// Output:
//   none
// Conditions:
// 	none
void Scheduler_SwitchInNextPriorityTask( void );

// ----------------------------------------
// Scheduler_MoveTaskNodeToReadyQueue
// 
// Moves a task node from the queue it is contained in to the ready Queue
// Input:
//  taskList: A pointer to the list node where the task is located.
// Output:
//   none
// Conditions:
// 	none
BOOL Scheduler_MoveTaskNodeToReadyQueue(linkedList_Handle taskToAddNode);

// ----------------------------------------
// Scheduler_GetCurrentlyRunningTask
// 
//  Returns a pointer to the currently running task's TCB
//
// Input:
// 	None
// Output:
//   A pointer to the currently running task's TCB
// Conditions:
// 	none
TCB * Scheduler_GetCurrentlyRunningTask(void);

// ----------------------------------------
// Scheduler_GetCurrentlyRunningTaskNode
// 
//  Returns a pointer to the currently running task's link list node
//
// Input:
// 	None
// Output:
//   A pointer to the currently running task's link list node
// Conditions:
// 	none
linkedList_Handle Scheduler_GetCurrentlyRunningTaskNode(void);

// ----------------------------------------
// Scheduler_TemporarilyPromoteThread
// 
//  Temporarily promotes a threads priority. Promotion is done
//	by placing it on the ready queue at a higher priority level.
//
//	Note: 	The funciton assumes that p is of higher priority than
//			the task priority. If p is a lower priorty than the task
//			priority then the task will actually be demoted.
//
//			The task will only be promoted for 1 time quantum
//			during this time it will get the opportunity to finish
//			what it has to do and releas its resource lock.
//
// Input:
// 	taskNode:	A pointer to the link list node that contains the 
//				task which is to be promoted.
//	p:			The priority that the task is to be promoted to.
// Output:
//   A pointer to the currently running task's link list node
// Conditions:
// 	none
BOOL Scheduler_TemporarilyPromoteThread( linkedList_Handle taskNode, PRIORITY p);

// ----------------------------------------
// Scheduler_Start
// 
//  Starts the kernels scheduler
//	the function will never return from here.
//
// Input:
// 	idleTaskHook: a function pointer to the idle task created by the user
//					if this is null the kernel has a default idle task that 
//					will run. This is just an infinite loop.
// Output:
//   none:
// Conditions:
// 	The threads the you want to run after this function is called
//	have to have been created before this function is called.
void Scheduler_Start( vFunc_ptr idleTaskHook);

#endif
